home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / ban.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  9KB  |  402 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: ban.c,v 1.53 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <errno.h>
  12. #include <limits.h>
  13. #include "opennap.h"
  14. #include "debug.h"
  15.  
  16. void
  17. free_ban (BAN * b)
  18. {
  19.     if (b)
  20.     {
  21.     if (b->target)
  22.         FREE (b->target);
  23.     if (b->setby)
  24.         FREE (b->setby);
  25.     if (b->reason)
  26.         FREE (b->reason);
  27.     FREE (b);
  28.     }
  29. }
  30.  
  31. char   *
  32. normalize_ban ( /*const */ char *src, char *dest, int destlen)
  33. {
  34.     /* normalize the ban to the full user!host syntax */
  35.     if (strchr (src, '!'))
  36.     return src;        /* already in proper format */
  37.     else if (invalid_nick (src))
  38.     {
  39.     char   *star;
  40.  
  41.     /* append a star if the last char is a . so that it means the same
  42.      * as the old-style ban
  43.      */
  44.     if (*src && src[strlen (src) - 1] == '.')
  45.         star = "*";
  46.     else
  47.         star = "";
  48.     snprintf (dest, destlen, "*!%s%s", src, star);    /* must be an ip/dns name? */
  49.     }
  50.     else
  51.     snprintf (dest, destlen, "%s!*", src);    /* must be a nick */
  52.     return dest;
  53. }
  54.  
  55. /* 612 [ :<sender> ] <user!ip> [ "<reason>" [time] ] */
  56. HANDLER (ban)
  57. {
  58.     BAN    *b;
  59.     LIST   *list;
  60.     int     ac = -1;
  61.     char   *av[3], *sendernick;
  62.     char   *banptr, realban[256];
  63.     USER   *sender;
  64.     int     timeout = 0;
  65.  
  66.     (void) len;
  67.     ASSERT (validate_connection (con));
  68.  
  69.     if (pop_user_server (con, tag, &pkt, &sendernick, &sender))
  70.     return;
  71.     if (sender && sender->level < LEVEL_MODERATOR)
  72.     {
  73.     permission_denied (con);
  74.     return;
  75.     }
  76.     if (pkt)
  77.     ac = split_line (av, FIELDS (av), pkt);
  78.     if (ac < 1)
  79.     {
  80.     unparsable (con);
  81.     return;
  82.     }
  83.  
  84.     if (ac > 2)
  85.     {
  86.     timeout = atoi (av[2]);
  87.     if (timeout < 0)
  88.     {
  89.         if (ISUSER (con))
  90.         send_cmd (con, MSG_SERVER_NOSUCH, "invalid ban timeout");
  91.         return;
  92.     }
  93.     }
  94.  
  95.     banptr = normalize_ban (av[0], realban, sizeof (realban));
  96.  
  97.     /* check to see if this user is already banned */
  98.     for (list = Bans; list; list = list->next)
  99.     {
  100.     b = list->data;
  101.     if (!strcasecmp (banptr, b->target))
  102.     {
  103.         if (ISUSER (con))
  104.         send_cmd (con, MSG_SERVER_NOSUCH, "already banned");
  105.         return;
  106.     }
  107.     }
  108.  
  109.     if (ac > 1)
  110.     truncate_reason (av[1]);
  111.  
  112.     pass_message_args (con, tag, ":%s %s \"%s\" %d", sendernick,
  113.                av[0], ac > 1 ? av[1] : "", timeout);
  114.  
  115.     do
  116.     {
  117.     /* create structure and add to global ban list */
  118.     if (!(b = CALLOC (1, sizeof (BAN))))
  119.         break;
  120.     if (!(b->target = STRDUP (banptr)))
  121.         break;
  122.     if (!(b->setby = STRDUP (sendernick)))
  123.         break;
  124.     if (!(b->reason = STRDUP (ac > 1 ? av[1] : "")))
  125.         break;
  126.     b->when = global.current_time;
  127.     b->timeout = timeout;
  128.  
  129.     list = CALLOC (1, sizeof (LIST));
  130.     if (!list)
  131.     {
  132.         OUTOFMEMORY ("ban");
  133.         break;
  134.     }
  135.     list->data = b;
  136.     list->next = Bans;
  137.     Bans = list;
  138.     notify_mods (BANLOG_MODE,
  139.              "%s%s banned %s%s%s%s: %s",
  140.              !sender ? "Server " : "",
  141.              sendernick, b->target,
  142.              (timeout > 0) ? " for " : "",
  143.              (timeout > 0) ? av[2] : "",
  144.              (timeout > 0) ? " seconds" : "", b->reason);
  145.     return;
  146.     }
  147.     while (1);
  148.  
  149.     /* we only get here on error */
  150.     OUTOFMEMORY ("ban");
  151.     free_ban (b);
  152.     if (list)
  153.     FREE (list);
  154. }
  155.  
  156. /* 614 [ :<sender> ] <nick!ip> [ "<reason>" ] */
  157. HANDLER (unban)
  158. {
  159.     USER   *user;
  160.     LIST  **list, *tmpList;
  161.     BAN    *b;
  162.     int     ac = -1;
  163.     char   *av[2];
  164.     char   *banptr, realban[256];
  165.  
  166.     (void) tag;
  167.     (void) len;
  168.  
  169.     ASSERT (validate_connection (con));
  170.     if (pop_user (con, &pkt, &user) != 0)
  171.     return;
  172.     if (pkt)
  173.     ac = split_line (av, FIELDS (av), pkt);
  174.     if (ac < 1)
  175.     {
  176.     unparsable (con);
  177.     return;
  178.     }
  179.     if (user->level < LEVEL_MODERATOR)
  180.     {
  181.     if (ISUSER (con))
  182.         permission_denied (con);
  183.     return;
  184.     }
  185.     banptr = normalize_ban (av[0], realban, sizeof (realban));
  186.     if (ac > 1)
  187.     truncate_reason (av[1]);
  188.     for (list = &Bans; *list; list = &(*list)->next)
  189.     {
  190.     b = (*list)->data;
  191.     if (!strcasecmp (banptr, b->target))
  192.     {
  193.         tmpList = *list;
  194.         *list = (*list)->next;
  195.         FREE (tmpList);
  196.         notify_mods (BANLOG_MODE, "%s removed ban on %s: %s",
  197.              user->nick, b->target, ac > 1 ? av[1] : "");
  198.         pass_message_args (con, tag, ":%s %s \"%s\"", user->nick,
  199.                    b->target, ac > 1 ? av[1] : "");
  200.         free_ban (b);
  201.         return;
  202.     }
  203.     }
  204.     if (ISUSER (con))
  205.     send_cmd (con, MSG_SERVER_NOSUCH, "no such ban");
  206. }
  207.  
  208. /* 615 */
  209. /* show the list of current bans on the server */
  210. HANDLER (banlist)
  211. {
  212.     LIST   *list;
  213.     BAN    *ban;
  214.  
  215.     (void) tag;
  216.     (void) len;
  217.     (void) pkt;
  218.     ASSERT (validate_connection (con));
  219.     CHECK_USER_CLASS ("banlist");
  220.     for (list = Bans; list; list = list->next)
  221.     {
  222.     ban = list->data;
  223.     send_cmd (con, MSG_SERVER_IP_BANLIST /* 616 */ ,
  224.           "%s %s \"%s\" %u %d", ban->target, ban->setby,
  225.           ban->reason, ban->when, ban->timeout);
  226.     }
  227.     /* terminate the banlist */
  228.     send_cmd (con, MSG_CLIENT_BANLIST /* 615 */ , "");
  229. }
  230.  
  231. int
  232. check_ban (CONNECTION * con, const char *nick, const char *host)
  233. {
  234.     LIST   *list;
  235.     BAN    *ban;
  236.     char    mask[256];
  237.  
  238.     snprintf (mask, sizeof (mask), "%s!%s", nick, host);
  239.     for (list = Bans; list; list = list->next)
  240.     {
  241.     ban = list->data;
  242.     if ((ban->timeout == 0 || ban->when + ban->timeout > global.current_time) &&
  243.         glob_match (ban->target, mask))
  244.     {
  245.         notify_mods (BANLOG_MODE,
  246.              "Connection from %s: %s banned: %s",
  247.              mask, ban->target, NONULL (ban->reason));
  248.         if (ISUNKNOWN (con))
  249.         {
  250.         send_cmd (con, MSG_SERVER_ERROR,
  251.               "%s banned: %s", ban->target, NONULL (ban->reason));
  252.         destroy_connection (con);
  253.         }
  254.         else if (ISSERVER (con))
  255.         {
  256.         /* issue a kill to remove this banned user */
  257.         pass_message_args (con, MSG_CLIENT_KILL,
  258.                    ":%s %s %s banned: %s", Server_Name, nick,
  259.                    ban->target, NONULL (ban->reason));
  260.         notify_mods (KILLLOG_MODE,
  261.                  "Server %s killed %s: %s banned: %s",
  262.                  Server_Name, nick, ban->target,
  263.                  NONULL (ban->reason));
  264.         }
  265.         return 1;
  266.     }
  267.     }
  268.     return 0;
  269. }
  270.  
  271. int
  272. save_bans (void)
  273. {
  274.     FILE   *fp;
  275.     LIST   *list;
  276.     BAN    *b;
  277.     char    path[_POSIX_PATH_MAX];
  278.  
  279.     snprintf (path, sizeof (path), "%s/bans", Config_Dir);
  280.     if ((fp = fopen (path, "w")) == 0)
  281.     {
  282.     logerr ("save_bans", path);
  283.     return -1;
  284.     }
  285.     for (list = Bans; list; list = list->next)
  286.     {
  287.     b = list->data;
  288.     fprintf (fp, "%s %s %u \"%s\" %d", b->target, b->setby,
  289.          (int) b->when, b->reason, b->timeout);
  290. #ifdef WIN32
  291.     fputc ('\r', fp);
  292. #endif
  293.     fputc ('\n', fp);
  294.     }
  295.     if (fclose (fp))
  296.     {
  297.     logerr ("save_bans", "fclose");
  298.     return -1;
  299.     }
  300.     return 0;
  301. }
  302.  
  303. int
  304. load_bans (void)
  305. {
  306.     FILE   *fp;
  307.     LIST   *list, **last = &Bans;
  308.     BAN    *b;
  309.     int     ac;
  310.     char   *av[5], path[_POSIX_PATH_MAX];
  311.     char   *banptr, realban[256];
  312.  
  313.     snprintf (path, sizeof (path), "%s/bans", Config_Dir);
  314.     if (!(fp = fopen (path, "r")))
  315.     {
  316.     if (errno != ENOENT)
  317.         logerr ("load_bans", path);
  318.     return -1;
  319.     }
  320.     while (fgets (Buf, sizeof (Buf) - 1, fp))
  321.     {
  322.     ac = split_line (av, FIELDS (av), Buf);
  323.     if (ac < 1)
  324.         continue;
  325.     b = CALLOC (1, sizeof (BAN));
  326.     if (!b)
  327.     {
  328.         OUTOFMEMORY ("load_bans");
  329.         fclose (fp);
  330.         return -1;
  331.     }
  332.     banptr = normalize_ban (av[0], realban, sizeof (realban));
  333.     b->target = STRDUP (banptr);
  334.     if (!b->target)
  335.     {
  336.         OUTOFMEMORY ("load_bans");
  337.         FREE (b);
  338.         break;
  339.     }
  340.     if (ac >= 4)
  341.     {
  342.         b->setby = STRDUP (av[1]);
  343.         b->when = atol (av[2]);
  344.         truncate_reason (av[3]);
  345.         b->reason = STRDUP (av[3]);
  346.         if (ac > 4)
  347.         b->timeout = atoi (av[4]);
  348.     }
  349.     else
  350.     {
  351.         /* old user ban style */
  352.         b->setby = STRDUP (Server_Name);
  353.         b->reason = STRDUP ("");
  354.         b->when = global.current_time;
  355.     }
  356.     list = CALLOC (1, sizeof (LIST));
  357.     if (!list)
  358.     {
  359.         OUTOFMEMORY ("load_bans");
  360.         free_ban (b);
  361.         fclose (fp);
  362.         return -1;
  363.     }
  364.     list->data = b;
  365.     /* keep the bans in the same order (roughly reverse chronological) */
  366.     *last = list;
  367.     last = &list->next;
  368.     }
  369.     fclose (fp);
  370.     return 0;
  371. }
  372.  
  373. /* reap expired bans from the list */
  374. void
  375. expire_bans (void)
  376. {
  377.     LIST  **list, *tmp;
  378.     BAN    *b;
  379.  
  380.     list = &Bans;
  381.     while (*list)
  382.     {
  383.     b = (*list)->data;
  384.     if (b->timeout > 0 && b->when + b->timeout < global.current_time)
  385.     {
  386.         tmp = *list;
  387.         *list = (*list)->next;
  388.         FREE (tmp);
  389.         /* make sure all servers are synched up */
  390.         pass_message_args (NULL, MSG_CLIENT_UNBAN,
  391.                    ":%s %s \"expired after %d seconds\"",
  392.                    Server_Name, b->target, b->timeout);
  393.         notify_mods (BANLOG_MODE,
  394.              "%s removed ban on %s: expired after %d seconds",
  395.              Server_Name, b->target, b->timeout);
  396.         free_ban (b);
  397.         continue;
  398.     }
  399.     list = &(*list)->next;
  400.     }
  401. }
  402.